﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#pragma once
#include "GbmpModel.h"
#include "ElementId.h"
#include "ElementCreationOptions.h"

#define  BMVI_UserDefined         L"BMVI_UserDefined"        // 未定义视图
#define  BMVI_BaseLevel           L"BMVI_BaseLevel"          // 基础标高
#define  BMVI_Ceiling             L"BMVI_Ceiling"            // 天花板
#define  BMVI_Right               L"BMVI_Right"              // 右视图
#define  BMVI_Left                L"BMVI_Left"               // 左视图
#define  BMVI_Front               L"BMVI_Front"              // 前视图
#define  BMVI_Back                L"BMVI_Back"               // 后视图
#define  BMVI_3D                  L"BMVI_3D"                 // 三维视图

namespace gcmp
{
    class IDocument;
    class IModelView;
    class IGbmpModelView;
    class IGbmpElevationView;
    class ILevel;
    class Vector3d;
    class Box3d;
    class TiltBox3d;
    class Coordinate3d;
    enum class BuiltInViewType;

    class GBMP_MODEL_EXPORT GbmpModelViewUtil
    {
    public:
        // 创建视图，及设置所有视图的通用行为。
        static IModelView* CreateModelView(IDocument* pDoc, const std::wstring& viewName, const BuiltInViewType& viewType,
            const Vector3d& viewDirection,
            const Vector3d& origin,
            const Vector3d& rightDirection,
            const Vector3d upDirection,
            ElementCreationOptions creationOption = ElementCreationOptions::Normal);

        //// 天花板视图（暂未实现）
        //static IModelView* CreateCeilingView(IDocument* pDoc, const std::wstring& viewName, ILevel* pLevel);

        // 是否为平面视图或天花板视图
        static bool IsPlanOrCeilingView(const IModelView* pModelView);

        // 内建立面视图
        static IGbmpElevationView* CreateEastElevationView(IDocument* pDoc);
        static IGbmpElevationView* CreateWestElevationView(IDocument* pDoc);
        static IGbmpElevationView* CreateSouthElevationView(IDocument* pDoc);
        static IGbmpElevationView* CreateNorthElevationView(IDocument* pDoc);

        static ElementId GetWorkLevelId(const IModelView* pModelView);
        static bool SetWorkLevelId(IModelView* pModelView, ElementId workLevelId);
        static ElementId GetLowestLevelId(IDocument* pDoc);

        // 根据同一类型中已有的视图，获取视图的下一个命名。
        // 规则：找出视图中最大的编号，再加1，即下一个视图编号。
        static bool GetNextModelViewName(IDocument* pDoc, const std::wstring& viewType, const std::wstring& viewNameBasePart, const std::wstring& separator, std::wstring& viewName);

        // 获取三维视图当前工作标高删除后的新工作标高（最低标高）
        static ElementId Get3DViewNextWorkLevel(const IDocument* pDoc, ElementId workLevelToBeDeleted);

        // 获取剖面视图当前工作标高删除后的新工作标高（最低标高）
        static ElementId GetSectionViewNextWorkLevel(const IDocument* pDoc, ElementId workLevelToBeDeleted);

        // 获取视图所有可见形体的总包围盒
        static bool GetAllVisibleGraphicsShapesBoundingBox(const IModelView* pModelView, Box3d& box);

        // 获取剖面视图的紧包围盒
        static bool GetSectionViewBox(const IModelView* pModelView, TiltBox3d& modelViewBox);

        // 视图的WorkPlane的名称
        static std::wstring GetWorkPlaneName(const IModelView* pModelView);
        static bool SetWorkPlaneName(const IModelView* pModelView, const std::wstring& name);

        // 视图的WorkPlane的ReferencePlane
        static bool SetReferencePlaneIdOfWorkPlane(IModelView* pModelView, const ElementId& refID);
        static ElementId GetReferencePlaneIdOfWorkPlane(const IModelView* pModelView);

        // 返回GraphicsPlane的坐标系
        static Coordinate3d GetWorkPlaneCoordinate(const IModelView* pModelView);

        static IModelView* FindViewByName(IDocument* pDoc, const std::wstring& viewType, const std::wstring& viewName);
        static IModelView* FindViewByBuiltinIndex(IDocument* pDoc, const std::wstring& viewType);

        static const IGbmpModelView* GetGbmpModelView(const IModelView* pModelView);
        static IGbmpModelView* GetGbmpModelView(IModelView* pModelView);

        // 判断给定视图平面是否与给定剖切盒上下表面平行
        static bool IsModelViewPlaneParallelToSectionBoxUpDownPlane(const Vector3d& pModelViewDir, const Vector3d& pSectionViewDir, const Vector3d& pSectionViewUpDir);
        // 判断给定视图平面是否与给定剖切盒左右表面平行
        static bool IsModelViewPlaneParallelToSectionBoxLeftRightPlane(const Vector3d& pModelViewDir, const Vector3d& pSectionViewDir, const Vector3d& pSectionViewUpDir);

    private:
        // 取出视图名称中的后缀编号，例如viewName:三维 1，viewNameBasePart:三维，则nSuffix返回1。
        static bool GetModelViewNameSuffix(const std::wstring& viewName, const std::wstring& viewNameBasePart, const std::wstring& separator, int& nSuffix);
    };
}
